/**
 * 
 */
package com.${ltdAbbr}.xiao.${module}.task.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.quartz.CalendarIntervalTrigger;
import org.quartz.CronTrigger;
import org.quartz.DailyTimeIntervalTrigger;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.triggers.CalendarIntervalTriggerImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.impl.triggers.DailyTimeIntervalTriggerImpl;
import org.quartz.impl.triggers.SimpleTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.${ltdAbbr}.xiao.${module}.task.po.TaskTriggerBo;
import com.${ltdAbbr}.xiao.${module}.task.service.SchedulerService;

/**
 * @author wangxiaoran-ds
 *
 */
@Component
public class SchedulerServiceImpl implements SchedulerService {

    //private static final Logger logger = Logger.getLogger(SchedulerServiceImpl.class);

    @Autowired
    private Scheduler scheduler;

    /**
     * 获取当前定时任务列表
     * @return
     * @throws Exception 
     */
    public List<TaskTriggerBo> queryTaskList() throws Exception{
        List<TaskTriggerBo> jtlist;
        List<String> groupNameList1 = scheduler.getJobGroupNames();
        if(groupNameList1==null||groupNameList1.size()<1){
            jtlist = new ArrayList<TaskTriggerBo>(0);
        }else{
            jtlist = new ArrayList<TaskTriggerBo>(100);
            //Map<String, String> taskNameMap = XYRemoteProppertiesUtil.getPropMap("job_name.properies");//XYPropertiesUtil.getPropertiesMap("props/task_name_map.properies");
            for(String groupName : groupNameList1){
                GroupMatcher<TriggerKey> groupMatcher = GroupMatcher.groupEquals(groupName);
                Iterator<TriggerKey> tkIt = scheduler.getTriggerKeys(groupMatcher).iterator();
                while(tkIt.hasNext()){
                    TriggerKey triggerKey = tkIt.next();
                    TaskTriggerBo taskTrigger = new TaskTriggerBo();
                    taskTrigger.setGroupName(triggerKey.getGroup());
                    taskTrigger.setTriggerName(triggerKey.getName());
                    Trigger trigger = scheduler.getTrigger(triggerKey);
                    taskTrigger.setJobName(trigger.getJobKey().getName());
                    if(trigger instanceof CronTrigger){//cron
                        taskTrigger.setCronExpression(((CronTrigger)trigger).getCronExpression());
                        taskTrigger.setTriggerType(TaskTriggerBo.TRIGGER_TYPE_CRON);
                    }else if(trigger instanceof SimpleTrigger){//固定间隔
                        SimpleTrigger simpleTrigger = (SimpleTrigger)trigger;
                        taskTrigger.setRepeatInterval(simpleTrigger.getRepeatInterval());
                        taskTrigger.setRepeatCount(simpleTrigger.getRepeatCount());
                        taskTrigger.setTriggeredTimes(simpleTrigger.getTimesTriggered());;
                        taskTrigger.setTriggerType(TaskTriggerBo.TRIGGER_TYPE_REPEAT_INTERVAL);
                        taskTrigger.setRepeatIntervalUnit(IntervalUnit.MILLISECOND.toString());
                    }else if(trigger instanceof DailyTimeIntervalTrigger){//每日固定间隔
                        DailyTimeIntervalTrigger dtiTrigger = (DailyTimeIntervalTrigger)trigger;
                        taskTrigger.setRepeatInterval((long)dtiTrigger.getRepeatInterval());
                        taskTrigger.setRepeatIntervalUnit(dtiTrigger.getRepeatIntervalUnit().name());
                        taskTrigger.setRepeatCount(dtiTrigger.getRepeatCount());
                        taskTrigger.setTriggeredTimes(dtiTrigger.getTimesTriggered());
                        taskTrigger.setTriggerType(TaskTriggerBo.TRIGGER_TYPE_DAILY_TIME_INTERVAL);
                    }else if(trigger instanceof CalendarIntervalTrigger){//日历固定间隔
                        CalendarIntervalTrigger ciTrigger = (CalendarIntervalTrigger)trigger;
                        taskTrigger.setRepeatInterval((long)ciTrigger.getRepeatInterval());
                        taskTrigger.setRepeatIntervalUnit(ciTrigger.getRepeatIntervalUnit().name());
                        taskTrigger.setTriggeredTimes(ciTrigger.getTimesTriggered());
                        taskTrigger.setTriggerType(TaskTriggerBo.TRIGGER_TYPE_CALENDAR_INTERVAL);
                    }else{
                        taskTrigger.setTriggerType(TaskTriggerBo.TRIGGER_TYPE_OTHER);
                    }
                    taskTrigger.setPreviousFireTime(trigger.getPreviousFireTime());
                    taskTrigger.setNextFireTime(trigger.getNextFireTime());
                    taskTrigger.setStatus(scheduler.getTriggerState(triggerKey));
//                    if(taskNameMap!=null){
//                        taskTrigger.setTaskName(taskNameMap.get(triggerKey.getName()));
//                    }
                    jtlist.add(taskTrigger);
                }
            }
        }
        Collections.sort(jtlist, new Comparator<TaskTriggerBo>() {
            public int compare(TaskTriggerBo o1, TaskTriggerBo o2) {
                String otn1 = (o1==null?null:o1.getTriggerName());
                String otn2 = (o2==null?null:o2.getTriggerName());
                return otn1==null?(otn2==null?0:1):(otn2==null?1:otn1.compareTo(otn2));
            }
        });
        return jtlist;
    }

    /**
     * 暂停定时任务
     * @param groupName
     * @param triggerName
     * @throws Exception 
     */
    public void pause(TaskTriggerBo jobTrigger) throws Exception {
        if(jobTrigger==null||StringUtils.isBlank(jobTrigger.getGroupName())||StringUtils.isBlank(jobTrigger.getTriggerName())){
            throw new IllegalArgumentException("groupName or triggerName is empty!");
        }
        scheduler.pauseTrigger(new TriggerKey(jobTrigger.getTriggerName(), jobTrigger.getGroupName()));
    }

    /**
     * 恢复定时任务运行
     * @param groupName
     * @param triggerName
     * @throws Exception
     */
    public void resume(TaskTriggerBo jobTrigger) throws Exception {
        if(jobTrigger==null||StringUtils.isBlank(jobTrigger.getGroupName())||StringUtils.isBlank(jobTrigger.getTriggerName())){
            throw new IllegalArgumentException("groupName or triggerName is empty!");
        }
        scheduler.resumeTrigger(new TriggerKey(jobTrigger.getTriggerName(), jobTrigger.getGroupName()));
    }

    /**
     * 立即运行定时任务
     * @param groupName
     * @param jobName
     * @throws Exception
     */
    public void run(TaskTriggerBo jobTrigger) throws Exception {
        if(jobTrigger==null||StringUtils.isBlank(jobTrigger.getGroupName())||StringUtils.isBlank(jobTrigger.getJobName())){
            throw new IllegalArgumentException("groupName or jobName is empty!");
        }
        scheduler.triggerJob(new JobKey(jobTrigger.getJobName(), jobTrigger.getGroupName()));
    }

    /**
     * 重设定时任务
     * 目前支持 [CronTriggerImpl, SimpleTriggerImpl, DailyTimeIntervalTriggerImpl, CalendarIntervalTriggerImpl] 共四种触发器定时任务
     * @param jobTrigger(groupName, triggerName, cronExpression||repeatInterval)
     * @throws Exception 
     */
    public void reset(TaskTriggerBo jobTrigger) throws Exception{
        if(jobTrigger==null||StringUtils.isBlank(jobTrigger.getGroupName())){
            throw new IllegalArgumentException("groupName or triggerName is empty!");
        }
        TriggerKey triggerKey = new TriggerKey(jobTrigger.getTriggerName(), jobTrigger.getGroupName());
        Trigger oldTrigger = scheduler.getTrigger(triggerKey);
        //重置cron定时任务
        if(oldTrigger instanceof CronTriggerImpl){
            if(StringUtils.isBlank(jobTrigger.getTriggerName())){
                throw new IllegalArgumentException("cronExpression is empty!");
            }else{
                ((CronTriggerImpl)oldTrigger).setCronExpression(jobTrigger.getCronExpression());
                scheduler.rescheduleJob(triggerKey, oldTrigger);
            }
        }else if(oldTrigger instanceof SimpleTriggerImpl){//固定间隔
            if(jobTrigger.getRepeatInterval()==null||jobTrigger.getRepeatInterval()<100L){
                throw new IllegalArgumentException("repeatInterval is null or less than 100!");
            }else{
                SimpleTriggerImpl simpleTrigger = (SimpleTriggerImpl)oldTrigger;
                if(jobTrigger.getRepeatCount()!=null && jobTrigger.getRepeatCount()>-2){
                    simpleTrigger.setRepeatCount(jobTrigger.getRepeatCount());
                }
                simpleTrigger.setRepeatInterval(jobTrigger.getRepeatInterval().intValue());
                scheduler.rescheduleJob(triggerKey, oldTrigger);
            }
        }else if(oldTrigger instanceof DailyTimeIntervalTriggerImpl){//每日固定间隔
            if(jobTrigger.getRepeatInterval()==null&&jobTrigger.getRepeatIntervalUnit()==null&&jobTrigger.getRepeatCount()==null){
                throw new IllegalArgumentException("repeatInterval or repeatIntervalUnit or repeatCount is null");
            }else if(jobTrigger.getRepeatInterval()!=null && jobTrigger.getRepeatInterval()<1L){
                throw new IllegalArgumentException("repeatInterval is less than 1");
            }else{
                DailyTimeIntervalTriggerImpl dtiTrigger = (DailyTimeIntervalTriggerImpl) oldTrigger;
                IntervalUnit repeatIntervalUnit = IntervalUnit.valueOf(jobTrigger.getRepeatIntervalUnit());
                if(repeatIntervalUnit!=null){
                    dtiTrigger.setRepeatIntervalUnit(repeatIntervalUnit);
                }
                if(jobTrigger.getRepeatInterval()!=null){
                    dtiTrigger.setRepeatInterval(jobTrigger.getRepeatInterval().intValue());
                }
                if(jobTrigger.getRepeatCount()!=null){
                    if(jobTrigger.getRepeatCount()<-1){
                        jobTrigger.setRepeatCount(-1);
                    }
                    dtiTrigger.setRepeatCount(jobTrigger.getRepeatCount());
                }
                scheduler.rescheduleJob(triggerKey, dtiTrigger);
            }
        }else if(oldTrigger instanceof CalendarIntervalTriggerImpl){//日历固定间隔
            if(jobTrigger.getRepeatInterval()==null&&jobTrigger.getRepeatIntervalUnit()==null){
                throw new IllegalArgumentException("repeatInterval or repeatIntervalUnit is null");
            }else if(jobTrigger.getRepeatInterval()!=null && jobTrigger.getRepeatInterval()<1L){
                throw new IllegalArgumentException("repeatInterval is less than 1");
            }else{
                CalendarIntervalTriggerImpl ciTrigger = (CalendarIntervalTriggerImpl) oldTrigger;
                IntervalUnit repeatIntervalUnit = IntervalUnit.valueOf(jobTrigger.getRepeatIntervalUnit());
                if(repeatIntervalUnit!=null){
                    ciTrigger.setRepeatIntervalUnit(repeatIntervalUnit);
                }
                if(jobTrigger.getRepeatInterval()!=null){
                    ciTrigger.setRepeatInterval(jobTrigger.getRepeatInterval().intValue());
                }
                scheduler.rescheduleJob(triggerKey, ciTrigger);
            }
        }else{
            throw new IllegalArgumentException("不支持的定时器类型:"+oldTrigger.getClass());
        }
    }
}
